use std::{sync::mpsc, thread, time::Duration};

pub fn learn_channel() {
  //_learn_channel0();
  //_learn_channel2();
  _learn_channel3();
}
// 当发送者或接收者任一被丢弃时,可以认为信道被关闭了
fn _learn_channel0() {
  // 创建一个信道,并将其两端赋值给tx和rx. mpsc是多个生产者,单个消费者的缩写
  // multiple producer,single consumer
  let (tx, rx) = mpsc::channel();

  thread::spawn(move || {
    let val = String::from("hi");
    tx.send(val).unwrap();
  });

  // recv()方法会阻塞主线程直到从信道中收到一个值
  // 当信道发送端关闭,recv会返回一个错误表明不会再有新的值到来了.
  let received = rx.recv().unwrap();
  println!("Got:{}", received);
}

// 信道与所有权转移
fn _learn_channel1() {
  let (tx, rx) = mpsc::channel();
  thread::spawn(move || {
    let val = String::from("hi");
    tx.send(val).unwrap();
    // val已经被send方法移动了
    // println!("val is {}", val);
  });
  let received = rx.recv().unwrap();
  println!("Got:{}", received);
}

// 发送多个值并观察接收者的等待
fn _learn_channel2() {
  let (tx, rx) = mpsc::channel();
  thread::spawn(move || {
    let vals = [
      String::from("hi"),
      String::from("from"),
      String::from("the"),
      String::from("thread"),
    ];
    for val in vals {
      tx.send(val).unwrap();
      thread::sleep(Duration::from_secs(1))
    }
  });
  // 将rx当做一个迭代器.当信道被关闭时,迭代器也将结束.
  for received in rx {
    println!("Got:{}", received);
  }
}

// 通过克隆发送者来创建多个生产者
fn _learn_channel3() {
  let (tx, rx) = mpsc::channel();
  let tx1 = tx.clone();
  thread::spawn(move || {
    let vals = [
      String::from("hi"),
      String::from("from"),
      String::from("the"),
      String::from("thread"),
    ];
    for val in vals {
      tx1.send(val).unwrap();
      thread::sleep(Duration::from_secs(1))
    }
  });
  thread::spawn(move || {
    let vals = [
      String::from("more"),
      String::from("messages"),
      String::from("for"),
      String::from("you"),
    ];
    for val in vals {
      tx.send(val).unwrap();
      thread::sleep(Duration::from_secs(1))
    }
  });
  for received in rx {
    println!("Got:{}", received);
  }
}
